#include "dragdoublespinbox.h"
#include <QLineEdit>
#include <QApplication>
#include <QEvent>
#include <QMouseEvent>
#include <QDebug>


#define DEFAULT_RANGELENGTH 300


#if 0   //使用示例
ui->doubleSpinBox->setRange(-100.123, 211.15);
ui->doubleSpinBox->SetRangeLength(600);
#endif

DragDoubleSpinBox::DragDoubleSpinBox(QWidget *parent) :
    QDoubleSpinBox(parent),
    m_isDragging(false),
    m_canDragSetVaule(true),
    m_rangeLength(DEFAULT_RANGELENGTH)
{
    setButtonSymbols(QAbstractSpinBox::NoButtons);
    lineEdit()->installEventFilter(this);
}

void DragDoubleSpinBox::SetRangeLength(int length)
{
    if (length <= 0) {
        SetCanDragSetValue(false);
    } else {
        m_rangeLength = length;
        SolveScale();
    }
}

void DragDoubleSpinBox::SetCanDragSetValue(bool dragSetValue)
{
    m_canDragSetVaule = dragSetValue;
}

void DragDoubleSpinBox::setRange(double minimum, double maximum)
{
    QDoubleSpinBox::setRange(minimum, maximum);
    SolveScale();
}

void DragDoubleSpinBox::enterEvent(QEvent *event)
{
    QDoubleSpinBox::enterEvent(event);
    QApplication::setOverrideCursor(QCursor(Qt::SizeHorCursor));
}

void DragDoubleSpinBox::leaveEvent(QEvent *event)
{
    if (!m_isDragging) {
        QApplication::restoreOverrideCursor();
    }
    QDoubleSpinBox::leaveEvent(event);
}


bool DragDoubleSpinBox::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == lineEdit()) {
        if (event->type() == QEvent::MouseButtonPress) {
            if (CanDragSetValue()) {
                QMouseEvent *e = static_cast<QMouseEvent *>(event);
                if (e) {
                    m_isDragging = true;
                    m_pressedPoint = e->pos();
                    m_pressedValue = value();
                    SolveLeftRightLength();
                }
            }
        } else if (event->type() == QEvent::MouseButtonRelease) {
            if (m_isDragging) {
                m_isDragging = false;
            }
        } else if (event->type() == QEvent::MouseMove) {
            if (CanDragSetValue() && m_isDragging) {
                QMouseEvent *e = static_cast<QMouseEvent *>(event);
                if (e) {
                    double newValue = 0;
                    int distance = e->pos().x() - m_pressedPoint.x();
                    if (distance <= -m_leftLength) {
                        newValue = minimum();
                    } else if (distance >= m_rightLength) {
                        newValue = maximum();
                    } else {
                        newValue = m_pressedValue + distance * m_scale;
                    }
                    setValue(newValue);
                }
                return true;
            }
        }
    }
    return QDoubleSpinBox::eventFilter(watched, event);
}

//比例关系为  value / px
void DragDoubleSpinBox::SolveScale()
{
    double range = maximum() - minimum();
    int length = m_rangeLength;
    if (m_rangeLength <= 0) {
        m_scale = 1;
        return ;
    }
    m_scale = range / (double)length;
    qDebug() << "scale: " << m_scale;
}

void DragDoubleSpinBox::SolveLeftRightLength()
{
    double leftValueRange = value() - minimum();
    if (leftValueRange >= 0 && m_scale > 0) {
        m_leftLength = leftValueRange / m_scale;
        m_rightLength = m_rangeLength - m_leftLength > 0 ? m_rangeLength - m_leftLength : 0;
    }
}
